/**
 *******************************************************************************
 *                 Copyright (C) 2017 - 2019  Accumulate Team                  *
 *                                                                             *
 *      Licensed under the Apache License, Version 2.0 (the "License");        *
 *      you may not use this file except in compliance with the License.       *
 *      You may obtain a copy of the License at                                *
 *                 http://www.apache.org/licenses/LICENSE-2.0                  *
 *                                                                             *
 *   Unless required by applicable law or agreed to in writing, software       *
 *   distributed under the License is distributed on an "AS IS" BASIS,         *
 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  *
 *   See the License for the specific language governing permissions and       *
 *   limitations under the License.                                            *
 *******************************************************************************
 * @file       sm_port.c                                                       *
 * @author     Accumulate Team                                                 *
 * @version    1.0.0                                                           *
 * @date       2018-12-13                                                      *
 * @brief      framework state machine port component source files             *
 * @par        work platform                                                   *
 *                 Windows                                                     *
 * @par        compiler                                                        *
 *                 GCC                                                         *
 *******************************************************************************
 * @note                                                                       *
 * 1.20181213    创建文件                                                      *
 *******************************************************************************
 */

/**
 * @defgroup framework state machine port component
 * @{
 */

/* Includes ------------------------------------------------------------------*/
#include "sm_core.h"

/* Exported macro ------------------------------------------------------------*/

/* Exported types ------------------------------------------------------------*/

/* Private variables ---------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief        状态机管理句柄定义
 *******************************************************************************
 */
struct SM_MANAGEMENT_PORT
{
    struct SM_CORE_HANDLE parent;

    //! 消息队列句柄
    sm_msg_t mq_buf[STATE_MACHINE_MESSAGE_QUEUE_MAX];
    FwMQ_t mq;

    //! 定义定时器句柄
    FwTimer_t timer;

    //! 定义任务句柄
    FwTask_t task;
};

/* Exported variables --------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief       SM句柄
 *******************************************************************************
 */
struct SM_MANAGEMENT_PORT smHandle;

/* Private functions ---------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief       定时器组件超时处理回调
 * @param       [in]   *handle   状态机句柄
 * @return      [out]  void
 * @note        static
 *******************************************************************************
 */
static void sm_core_timer_callback(void *param)
{
    struct SM_MANAGEMENT_PORT *sm = (struct SM_MANAGEMENT_PORT *)param;

    Fw_MQ_Send(&sm->mq, &(sm_msg_t){.obj = 0, .sig = SM_CORE_TICK_EVENT}, sizeof(sm_msg_t));
}

/**
 *******************************************************************************
 * @brief       SM 内核任务处理函数
 * @param       [in]   *param    SM 管理句柄
 * @return      [out]  void
 * @note        static
 *******************************************************************************
 */
static void sm_core_task(void *param)
{
    struct SM_MANAGEMENT_PORT *sm = (struct SM_MANAGEMENT_PORT *)param;
    
    sm_msg_t evt;

    while (1)
    {
        Fw_MQ_Recv(&sm->mq, &evt, sizeof(evt));

        switch (evt.sig)
        {
            case SM_CORE_TICK_EVENT:
                sm_timer_process(&sm->parent);
                break;
            default:
                sm_core_process(NULL, &evt);
                break;
        }
    }
}

/* Exported functions --------------------------------------------------------*/
/**
 *******************************************************************************
 * @brief       SM 获取系统时钟API
 * @param       [in]   void
 * @return      [out]  sm_tick_t    系统时钟
 * @note        sm component内部调用
 *******************************************************************************
 */
__INLINE sm_tick_t sm_tick_get(void)
{
    return Fw_Tick_Get();
}

/**
 *******************************************************************************
 * @brief       SM 消息派发API
 * @param       [in]   obj    SM OBJ ID
 * @param       [in]   sig    SM trigger signal
 * @return      [out]  void
 * @note        sm component内部调用
 *******************************************************************************
 */
__INLINE void sm_msg_post(sm_obj_t *obj, uint32_t msg, void *param)
{
    sm_msg_t send;

    send.obj   = (struct SM_OBJECT *)obj;
    send.sig   = (enum SM_EVENT_DEFINE)(msg == 0 ? SM_TIMEOUT_EVENT : msg);
    send.param = param;

    Fw_MQ_Send(&smHandle.mq, &send, sizeof(send));
}

/**
 *******************************************************************************
 * @brief       获取SM管理句柄
 * @param       [in]   void
 * @return      [out]  SM 管理句柄
 * @note        sm component内部调用
 *******************************************************************************
 */
struct SM_CORE_HANDLE *sm_core(void)
{
    return &smHandle.parent;
}

/**
 *******************************************************************************
 * @brief       状态机父对象始化
 * @param       [in]   *sm        状态机对象
 * @param       [in]   *name      状态机名称
 * @return      void
 * @note        sm component内部调用
 *******************************************************************************
 */
__INLINE void sm_parent_init(sm_obj_t *sm, char *name)
{
    fwbus_obj_attach(&sm->parent_class,
                     (enum FW_BUS_OBJECT_TYPE)((sm->attribute.is_dynamic ?  FW_OBJ_TYPE_STATIC : 0) | FW_OBJ_TYPE_STATE_MECHINE), 
                     name);
}

/**
 *******************************************************************************
 * @brief       获取设备名称
 * @param       [in]   *parent    父类对象
 * @return      [out]  char*      状态机名称
 * @note        sm component内部调用
 *******************************************************************************
 */
__INLINE char *sm_obj_name(sm_obj_t *sm)
{
    return (char *)sm->parent_class.name;
}

/**
 *******************************************************************************
 * @brief       状态机内核初始化
 * @param       [in]   void
 * @return      [out]  int       0:successed
 * @note        sm component内部调用
 *******************************************************************************
 */
int sm_component_init(void)
{  
    //! 初始化sm句柄
    memset(&smHandle, 0, sizeof(smHandle));

    //! 定时器组件初始化
    sm_core_init(&smHandle.parent);

    //! 定时器组件初始化
    Fw_Timer_Init(&smHandle.timer, 
                  SM_COMPONENT_NAME"_tim",
                  sm_core_timer_callback,
                  (void *)&smHandle,
                  1,
                  FW_TIM_EN_PERIOD);

    //! 创建消息队列
    Fw_MQ_Init(&smHandle.mq, (void *)smHandle.mq_buf, sizeof(smHandle.mq_buf));

    //! 创建任务
    Fw_Task_Init(&smHandle.task,
                 SM_COMPONENT_NAME"_task",
                 sm_core_task,
                 (void *)&smHandle,
                 SM_TASK_PRIO,
                 0);

    //! 启动任务
    Fw_Task_Start(&smHandle.task);

    return 0;
}
INIT_APP_EXPORT(sm_component_init);

/** @}*/     /** framework state machine port component */

/**********************************END OF FILE*********************************/
